#include "Personnage.h"
#include "Personnage_private.h"

#include "Joueur.h"
#include "Plateau.h"

#include "Erreur.h"

/* Constructor */
Personnage* newPersonnage(int exp,int vie,Pouvoir* pouvoir,Case* c,Joueur* joueur){
	Personnage* perso;
	
	perso = emalloc(sizeof(Personnage));
	if(perso == NULL) return NULL;

	persoSetExperience(perso,exp);
	persoSetVie(perso,vie);
	persoSetPouvoir(perso,pouvoir);
	persoSetCase(perso,c);
	persoSetJoueur(perso,joueur);
	
	return perso;
}

/* Destructor */
void deletePersonnage(Personnage* perso){
	if(perso == NULL) return;
	
	if(perso->free)
		perso->free(perso);
	free(perso);
}

/* Getters */
int persoGetExperience(Personnage* perso){
	if(perso == NULL) return -1;
	
	return perso->exp;
}
int persoGetVie(Personnage* perso){
	if(perso == NULL) return -1;
	
	return perso->vie;
}
TypePerso persoGetType(Personnage* perso){
	if(perso == NULL) return tpUndefined;
	
	return perso->type;
}
Pouvoir* persoGetPouvoir(Personnage* perso){
	if(perso == NULL) return NULL;
	
	return perso->pouvoir;
}
Case* persoGetCase(Personnage* perso){
	if(perso == NULL) return NULL;
	
	return perso->c;
}
Joueur* persoGetJoueur(Personnage* perso){
	if(perso == NULL) return NULL;
	
	return perso->joueur;
}
const char* persoGetTypeNom(Personnage* perso){
	if(perso == NULL) return NULL;
	
	if(perso->getTypeNom)
		return perso->getTypeNom(perso);
	
	return "Personnage";
}
void* persoGetExt(Personnage* perso){
	if(perso == NULL) return NULL;
	
	return perso->ext;
}
int persoIsFreezed(Personnage* perso){
	if(perso == NULL) return 1;
	
	return perso->freezed;
}
int persoIsMort(Personnage* perso){
	return persoGetVie(perso) <= 0;
}

/* Settlers */
void persoSetExperience(Personnage* perso,int experience){
	if(perso == NULL) return;
	
	perso->exp = experience;
}
void persoSetVie(Personnage* perso,int vie){
	if(perso == NULL) return;
	
	perso->vie = vie;
}
void persoAddVie(Personnage* perso,int nbVie){
	eassert(perso != NULL);
	
	perso->vie = (persoGetVie(perso) + nbVie > persoGetExperience(perso))?(persoGetExperience(perso)):(persoGetVie(perso) + nbVie);
}
void persoSetType(Personnage* perso,TypePerso type){
	if(perso == NULL) return;
	
	perso->type = type;
}
void persoSetPouvoir(Personnage* perso,Pouvoir* pouvoir){
	if(perso == NULL) return;
	
	perso->pouvoir = pouvoir;
	if(pouvoir != NULL && pouvoirGetPersonnage(pouvoir) != perso)
		pouvoirSetPersonnage(pouvoir,perso);
}
void persoSetCase(Personnage* perso,Case* c){
	if(perso == NULL) return;
	
	if(persoGetCase(perso) == c) return;
	
	caseEnleverPerso(persoGetCase(perso),perso);
	
	perso->c = c;
	if(c != NULL && listPosOf(caseGetPersos(c),perso) == LIST_INVALIDPOS){
		plateauPlacerEn(caseGetPlateau(c),c,perso);
	}
}

void persoSetJoueur(Personnage* perso,Joueur* joueur){
	if(perso == NULL) return;
	
	perso->joueur = joueur;
	if(joueur != NULL && !joueurHasPerso(joueur,perso))
		joueurAddPerso(joueur,perso);
}

void persoSetExt(Personnage* perso,void* ext){
	if(perso == NULL) return;
	
	perso->ext = ext;
}
void persoFreeze(Personnage* perso){
	if(perso == NULL) return;
	
	perso->freezed++;
}
void persoFreezeFor(Personnage* perso,int nbTours){
	if(perso == NULL) return;
	
	perso->freezed += nbTours;
}
int persoUnFreeze(Personnage* perso){
	if(perso == NULL) return 1;
	
	return perso->freezed--;
}
void persoUnFreezeForce(Personnage* perso){
	if(perso == NULL) return;
	
	perso->freezed = 0;
}

int persoAttaquer(Personnage* perso,Personnage* ennemi){
	int force;
	if(perso == NULL) return 0;
	
	if(perso->attaquer)
		return perso->attaquer(perso,ennemi);
	
	force = desLancer10();
	/* On pondère la force de l'attaque avec l'experience du personnage */
	force = force * (persoGetExperience(perso)/100);
	
	persoRecevoirAttaque(ennemi,force);
	return 1;
}

void persoRecevoirAttaque(Personnage* perso,int force){
	int vie;
	
	vie = persoGetVie(perso) - force;
	persoSetVie(perso,(vie > 0)?vie:0);
}

int persoRessuciter(Personnage* perso){
	eassert(perso != NULL);
	
	/* TODO : persoRessuciter.. Héritage et chaque perso sait se réssuciter */
	
	/* Vous avez déja réssucité un gars qui n'est pas mort vous? */
	if(!persoIsMort(perso)) return 0;
	
	persoSetVie(perso,persoGetExperience(perso));
	
	/* Gérer là remise à la case départ hors de cette méthode, c'est le rôle du plateau pas du perso de se déplacer! */
	
	return 1;
}
